package com.yulan.fastkillcourse.controller;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yulan.fastkillcourse.common.Const;
import com.yulan.fastkillcourse.model.Course;
import com.yulan.fastkillcourse.model.CourseMargin;
import com.yulan.fastkillcourse.model.CourseOrder;
import com.yulan.fastkillcourse.mq.FastKillMessage;
import com.yulan.fastkillcourse.mq.MQSender;
import com.yulan.fastkillcourse.redis.RedisService;
import com.yulan.fastkillcourse.redis.key.CourseKey;
import com.yulan.fastkillcourse.result.CodeMsg;
import com.yulan.fastkillcourse.result.Result;
import com.yulan.fastkillcourse.service.CourseMarginService;
import com.yulan.fastkillcourse.service.CourseOrderService;
import com.yulan.fastkillcourse.service.CourseService;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 抢课中心
 */
@Controller
@RequestMapping("fastkill")
public class FastKillController implements InitializingBean {


    @Autowired
    RedisService redisService;


    @Autowired
    CourseService courseService;

    @Autowired
    CourseOrderService courseOrderService;

    @Autowired
    MQSender mqSender;

    @Autowired
    CourseMarginService courseMarginService;

    private static AtomicInteger testUid = new AtomicInteger(1);


    private ConcurrentHashMap<Integer,Boolean> localOverMap = new ConcurrentHashMap<>();

    private ConcurrentHashMap<Integer,Integer> hasPickMap = new ConcurrentHashMap<>();


    @Override
    public void afterPropertiesSet() throws Exception {
        List<CourseMargin> CourseMarginList = courseMarginService.list();
        List<CourseOrder> courseOrderList = courseOrderService.list();
        if(CourseMarginList==null) return ;
        for(CourseMargin course:CourseMarginList){
            redisService.set(CourseKey.getFastKillCourseStock,""+ course.getCid(),course.getMargin(),
                    Const.RedisCacheExtime.COURSE_LIST);


            localOverMap.put(course.getCid(),course.getMargin() == 0);
        }

        for(CourseOrder courseOrder : courseOrderList){
            //K-V K:uid V:cid prefix是为了指定该k-v的类型 防止其他同样的k-v冲突
            redisService.set(CourseKey.getCourseOrder,""+courseOrder.getUid(),courseOrder.getCid(),
                    Const.RedisCacheExtime.COURSE_LIST);

            hasPickMap.put(courseOrder.getUid(),courseOrder.getCid());
        }

    }

    //抢课
    @RequestMapping(value = "/course", method = RequestMethod.POST)
    @ResponseBody
    public Result<Integer> list(@RequestParam("courseId") int courseId) {

        int uId = testUid.getAndIncrement();

        //内存标记，减少redis访问
        boolean over = localOverMap.getOrDefault(courseId,false);
        if(over) return Result.error(CodeMsg.MIAO_SHA_OVER);

        //判断是否有重复选课
        if(FastKillCourseOrderHelper(uId,courseId)) return Result.error(CodeMsg.REPEATE_MIAOSHA);

        int curMargin = redisService.get(CourseKey.getFastKillCourseStock,""+courseId,Integer.class);
        //判断余量是否大于0
        if(curMargin<=0) return Result.error(CodeMsg.MIAO_SHA_OVER);
        System.out.println("Redis_curMargin: "+curMargin);

        //预减余量
        long stock = redisService.decr(CourseKey.getFastKillCourseStock,""+courseId);
        System.out.println("Redis_stock: "+stock);
        if(stock<0){
            localOverMap.put(courseId,false);
            return Result.error(CodeMsg.MIAO_SHA_OVER);
        }

        FastKillMessage ms = new FastKillMessage();
        ms.setCid(courseId);
        ms.setUid(uId);
        mqSender.sendFastKillMessgae(ms);

        return Result.success(0);

    }


    //抢课
    @RequestMapping(value = "/testMQ", method = RequestMethod.POST)
    @ResponseBody
    public Result<Integer> testMQ(){
        int uId = testUid.incrementAndGet();
        FastKillMessage ms = new FastKillMessage();
        ms.setCid(1);
        ms.setUid(uId);
        mqSender.sendFastKillMessgae(ms);

        return Result.success(0);
    }

    @GetMapping("/result")
    @ResponseBody
    public Result<Integer> FastKillResult(@RequestParam int uid , @RequestParam int cid){
        int courseId = 0;
        if(redisService.get(CourseKey.getCourseOrder,""+uid,Integer.class)!=null){
            courseId = redisService.get(CourseKey.getCourseOrder,""+uid,Integer.class);
            if(courseId == cid) return new Result<>(1);

        }

        //如果redis查不到 就查数据库
        QueryWrapper<CourseOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("cid",cid).eq("uid",uid);

        CourseOrder courseOrder = courseOrderService.getOne(queryWrapper);
        if(courseOrder!=null) return new Result<>(1);
        //抢课失败
        return Result.success(-1);

    }



    /**
     *
     * @param uid 学生id
     * @param cid 课程id
     * @return 如果为真 则已选择该课程
     */
    public boolean FastKillCourseOrderHelper(int uid , int cid){
        //先查内存的hashMap
        if(hasPickMap.getOrDefault(uid,-1) == cid) return true;

        //再查redis有没有该选课信息
        if(redisService.get(CourseKey.getCourseOrder,""+uid,Integer.class)!=null){
            int cId = redisService.get(CourseKey.getCourseOrder,""+uid,Integer.class);
            if(cId == cid) return true;
        }
        //最后查数据库
        QueryWrapper<CourseOrder> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .eq("cid",cid)
                .eq("uid",uid);
        CourseOrder courseOrder = courseOrderService.getOne(queryWrapper);

        //更新redis
        if(courseOrder!=null)redisService.set(CourseKey.getCourseOrder,""+courseOrder.getUid(),courseOrder.getCid()
                ,Const.RedisCacheExtime.COURSE_LIST);

        //返回最终查询结果
        if(courseOrder!=null)
            return  courseOrder.getCid() == cid && courseOrder.getUid() == uid;
        else
            return  false;
    }


}
